package com.lou.springboot.service.impl;

import com.lou.springboot.common.PageResult;
import com.lou.springboot.dao.*;
import com.lou.springboot.entity.*;
import com.lou.springboot.enums.BlogStatusEnum;
import com.lou.springboot.enums.CommentStatusEnum;
import com.lou.springboot.service.BlogService;
import com.lou.springboot.utils.MarkDownUtil;
import com.lou.springboot.utils.PageUtil;
import com.lou.springboot.utils.PatternUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by Guaguaerhao on 2020/7/15 00:06
 */
@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogDao blogDao;

    @Autowired
    private BlogCommentDao blogCommentDao;

    @Autowired
    private BlogCategoryDao categoryDao;

    @Autowired
    private BlogTagDao blogTagDao;

    @Autowired
    private BlogTagRelationDao relationDao;

    @Override
    @Transactional
    public Object saveBlog(Blog blog) {
        // 1、根据分类获取分类名称
        BlogCategory blogCategory = categoryDao.selectByPrimaryKey(blog.getBlogCategoryId());
        if (blogCategory == null) {
            blog.setBlogCategoryId(0);
            blog.setBlogCategoryName("默认分类");
        } else {
            // 设置博客分类名称
            blog.setBlogCategoryName(blogCategory.getCategoryName());
            // 分类的排序值加1
            blogCategory.setCategoryRank(blogCategory.getCategoryRank() + 1);
        }
        // 2、根据标签，添加标签
        String[] tags = blog.getBlogTags().split(",");
        if (tags.length > 6) {
            return "标签数量限制为6";
        }
        // 3、保存文章
        Long r = blogDao.insertBlog(blog);
        if (r > 0) {
            // tagsForInsert集合用于收集数据库不存在的标签
            List<Tag> tagListForInsert = new ArrayList<>();
            //所有的tag对象，用于建立关系数据
            List<Tag> allTagsList = new ArrayList<>();
            for (String tagName : tags) {
                Tag dataTag = blogTagDao.selectByTagName(tagName);
                // tag不存在，则添加
                if (dataTag==null) {
                    Tag tag = new Tag();
                    tag.setTagName(tagName);
                    tagListForInsert.add(tag);
                } else {
                    allTagsList.add(dataTag);
                }
            }
            // 新增标签数据并修改分类排序值
            if (!CollectionUtils.isEmpty(tagListForInsert)) {
                blogTagDao.batchInsertBlogTag(tagListForInsert);
            }
            // 更新分类 rank 排序值
            categoryDao.updateCategory(blogCategory);
            List<BlogTagRelation> blogTagRelations = new ArrayList<>();
            // 新增关系数据
            allTagsList.addAll(tagListForInsert);
            for (Tag tag : allTagsList) {
                BlogTagRelation relation = new BlogTagRelation();
                relation.setBlogId(blog.getBlogId());
                relation.setTagId(tag.getTagId());
                blogTagRelations.add(relation);
            }
            if (relationDao.batchInsert(blogTagRelations) > 0) {
                return blog;
            }
        }
        return null;
    }

    @Override
    @Transactional
    public String updateBlog(Blog blog) {
        Blog blogForUpdate = blogDao.selectByPrimaryKey(blog.getBlogId());
        if (blogForUpdate == null) {
            return "数据不存在";
        }
        blogForUpdate.setBlogTitle(blog.getBlogTitle());
        blogForUpdate.setBlogSubUrl(blog.getBlogSubUrl());
        blogForUpdate.setBlogContent(blog.getBlogContent());
        blogForUpdate.setBlogCoverImage(blog.getBlogCoverImage());
        blogForUpdate.setBlogStatus(blog.getBlogStatus());
        blogForUpdate.setEnableComment(blog.getEnableComment());
        // 判断文章分类
        BlogCategory category = categoryDao.selectByPrimaryKey(blog.getBlogCategoryId());
        if (category == null) {
            blogForUpdate.setBlogCategoryId(0);
            blogForUpdate.setBlogCategoryName("默认分类");
        } else {
            // 设置博客分类名称
            blogForUpdate.setBlogCategoryId(blog.getBlogCategoryId());
            blogForUpdate.setBlogCategoryName(category.getCategoryName());
            // 分类的排序值加1
            category.setCategoryRank(category.getCategoryRank() + 1);
        }
        // 检测tags标签
        String[] tags = blog.getBlogTags().split(",");
        if (tags.length > 6) {
            return "标签最多6个";
        }
        blogForUpdate.setBlogTags(blog.getBlogTags());
        List<Tag> tagsForInsert = new ArrayList<>();
        List<Tag> existedTags = new ArrayList<>();
        // 遍历tags
        for(String tagName : tags) {
            Tag tag = blogTagDao.selectByTagName(tagName);
            if (tag == null) {
                Tag tagForInsert = new Tag();
                tagForInsert.setTagName(tagName);
                tagsForInsert.add(tagForInsert);
            } else {
                existedTags.add(tag);
            }
        }
        // 修改category的rank值
        categoryDao.updateCategory(category);
        // 删除原来的标签关联数据 -> 插入新标签 -> 更新现在的标签关联数据
        relationDao.deleteBatchByBlogId(blog.getBlogId());
        if (tagsForInsert.size() > 0) {
            blogTagDao.batchInsertBlogTag(tagsForInsert);
        }
        tagsForInsert.addAll(existedTags);
        List<BlogTagRelation> relations = new ArrayList<>();
        for (Tag tag : tagsForInsert) {
            BlogTagRelation relation = new BlogTagRelation();
            relation.setTagId(tag.getTagId());
            relation.setBlogId(blogForUpdate.getBlogId());
            relations.add(relation);
        }
        // 更新现在的标签关联数据
        relationDao.batchInsert(relations);
        // 更新文章
        if (blogDao.updateBlog(blogForUpdate) > 0) {
            return "success";
        }
        return "修改失败";
    }

    @Override
    public boolean deleteBatch(Long[] blogIds) {
        return blogDao.deleteBatch(blogIds) > 0;
    }

    @Override
    public Blog getBlog(Long blogId) {
        return blogDao.selectByPrimaryKey(blogId);
    }

    @Override
    public PageResult getBlogList(PageUtil pageUtil) {
        List<Blog> blogList = blogDao.findBlogList(pageUtil);
        int total = blogDao.getTotalBlog(null);
        return new PageResult(blogList, total, pageUtil.getLimit(), pageUtil.getPage());
    }

    @Override
    public PageResult getBlogsForIndexPage(int page) {
        Map map = new HashMap();
        map.put("page", page);
        map.put("limit", 8);
        map.put("blogStatus", 1); // 过滤发布状态下的数据
        PageUtil pageUtil = new PageUtil(map);
        List<Blog> blogs = blogDao.findBlogList(pageUtil);
        List<BlogListVO> blogListVOS = convertBlogsToBlogListVOs(blogs);
        int total = blogDao.getTotalBlog(null);
        return new PageResult(blogListVOS, total, pageUtil.getLimit(), pageUtil.getPage());
    }

    @Override
    public PageResult getBlogsPageBySearch(String keyword, int page) {
        if (page > 0 && PatternUtil.validKeyword(keyword)) {
            Map<String, Object> map = new HashMap<>();
            map.put("page", page);
            map.put("limit", 9);
            map.put("keyword", keyword);
            map.put("blogStatus", 1); // 过滤发布状态下的数据
            PageUtil pageUtil = new PageUtil(map);
            List<Blog> blogs = blogDao.findBlogList(pageUtil);
            int total = blogDao.getTotalBlog(pageUtil);
            List<BlogListVO> blogListVOS = convertBlogsToBlogListVOs(blogs);
            return new PageResult(blogListVOS, total, pageUtil.getLimit(),pageUtil.getPage());
        }
        return null;
    }

    @Override
    public List<SimpleBlogListVO> getBlogListForIndexPage(Integer type) {
        List<Blog> blogs = blogDao.getBlogListByType(type, 9);
        List<SimpleBlogListVO> simpleBlogListVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(blogs)) {
            simpleBlogListVOS = blogs.stream()
                    .map(blog -> new SimpleBlogListVO(blog.getBlogId(), blog.getBlogTitle()))
                    .collect(Collectors.toList());
        }
        return simpleBlogListVOS;
    }

    @Override
    public PageResult getBlogsPageByTagName(String tagName, int page) {
        Tag tag = blogTagDao.selectByTagName(tagName);
        if (tag != null && page > 0) {
            Map<String,Object> map = new HashMap<>();
            map.put("page", page);
            map.put("limit", 9);
            map.put("tagId", tag.getTagId());
            PageUtil pageUtil = new PageUtil(map);
            List<Blog> blogs = blogDao.findBlogListByTagId(pageUtil);
            List<BlogListVO> blogListVOS = convertBlogsToBlogListVOs(blogs);
            int total = blogDao.getTotalBlogsByTagId(pageUtil);
            return new PageResult(blogListVOS,total,pageUtil.getLimit(), pageUtil.getPage());
        }
        return null;
    }

    @Override
    public PageResult getBlogsPageByCategoryName(String categoryName, int page) {
        BlogCategory category = categoryDao.selectByCategoryName(categoryName);
        if (category != null) {
            Map<String,Object> map = new HashMap<>();
            map.put("page", page);
            map.put("limit", 9);
            map.put("blogStatus",1);
            map.put("blogCategoryId", category.getCategoryId());
            PageUtil pageUtil = new PageUtil(map);
            List<Blog> blogs = blogDao.findBlogList(pageUtil);
            List<BlogListVO> blogListVOS = convertBlogsToBlogListVOs(blogs);
            int total = blogDao.getTotalBlog(pageUtil);
            return new PageResult(blogListVOS, total, pageUtil.getLimit(),pageUtil.getPage());
        }
        return null;
    }

    @Override
    public boolean increaseBlogViews(Long blogId) {
        return blogDao.increaseBlogViews(blogId) > 0;
    }

    @Override
    public BlogDetailVO getBlogDetail(Long blogId) {
        Blog blog = blogDao.selectByPrimaryKey(blogId);
        // 过滤空且状态为已发布
        BlogDetailVO blogDetailVO = getBlogDetailVO(blog);
        if (blogDetailVO != null) {
            return blogDetailVO;
        }
        return null;
    }

    private BlogDetailVO getBlogDetailVO(Blog blog) {
        if (blog != null && blog.getBlogStatus() == 1) {
            // 增加浏览量
            blog.setBlogViews(blog.getBlogViews() + 1);
            int i = blogDao.updateBlog(blog);

            BlogDetailVO blogDetailVO = new BlogDetailVO();
            BeanUtils.copyProperties(blog, blogDetailVO);
            // md格式转换
            blogDetailVO.setBlogContent(MarkDownUtil.mdToHtml(blog.getBlogContent()));
            // 处理文章分类
            BlogCategory blogCategory = categoryDao.selectByPrimaryKey(blog.getBlogCategoryId());
            if (blogCategory == null) {
                blogCategory = new BlogCategory();
                blogCategory.setCategoryId(0);
                blogCategory.setCategoryName("默认分类");
                blogCategory.setCategoryIcon("/admin/dist/img/category/00.png");
            }
            // 分类信息
            blogDetailVO.setBlogCategoryIcon(blogCategory.getCategoryIcon());
            if (!StringUtils.isEmpty(blog.getBlogTags())) {
                // 标签设置
                List<String> tags = Arrays.asList(blog.getBlogTags().split(","));
                blogDetailVO.setBlogTags(tags);
            }

            // 处理评论数目
            Map map = new HashMap();
            map.put("blogId", blog.getBlogId());
            map.put("commentStatus", CommentStatusEnum.PASSED.getCode());
            int commentCount = blogCommentDao.getTotalCommentsByBlogId(map);
            blogDetailVO.setCommentCount(commentCount);

            return blogDetailVO;
        }
        return null;
    }

    /**
     * 数据处理
      */
    private List<BlogListVO> convertBlogsToBlogListVOs(List<Blog> blogs){
        List<BlogListVO> blogListVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(blogs)) {
            // 收集categoryIds
            List<Integer> categoryIds = blogs.stream().map(blog -> blog.getBlogCategoryId()).collect(Collectors.toList());
            Map<Integer,String> blogCategoryMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(categoryIds)) {
                // 根据categoryIds查询分类
                List<BlogCategory> categories = categoryDao.selectByCategoryIds(categoryIds);
                if (!CollectionUtils.isEmpty(categories)) {
                    // 构建 Map<categoryId, categoryIcon>
                    blogCategoryMap = categories.stream()
                            .collect(Collectors.toMap(BlogCategory::getCategoryId,
                                                      BlogCategory::getCategoryIcon,
                                                      (key1,key2) -> key2));
                }
                for (Blog blog : blogs) {
                    BlogListVO blogListVO = new BlogListVO();
                    BeanUtils.copyProperties(blog, blogListVO);
                    if (blogCategoryMap.containsKey(blog.getBlogCategoryId())) {
                        blogListVO.setBlogCategoryIcon(blogCategoryMap.get(blog.getBlogCategoryId()));
                    } else {
                        blogListVO.setBlogCategoryId(0);
                        blogListVO.setBlogCategoryName("默认分类");
                        blogListVO.setBlogCategoryIcon("/admin/dist/img/category/1.png");
                    }
                    blogListVOS.add(blogListVO);
                }
            }
        }
        return blogListVOS;
    }

}
